package com.zhaozhaonews.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.zhaozhaonews.api.article.IArticleClient;
import com.zhaozhaonews.common.aliyun.GreenImageScan;
import com.zhaozhaonews.common.aliyun.GreenTextScan;
import com.zhaozhaonews.file.service.FileStorageService;
import com.zhaozhaonews.model.article.dto.ArticleDto;
import com.zhaozhaonews.model.common.dto.ResponseResult;
import com.zhaozhaonews.model.wemedia.entity.WmChannel;
import com.zhaozhaonews.model.wemedia.entity.WmNews;
import com.zhaozhaonews.model.wemedia.entity.WmUser;
import com.zhaozhaonews.wemedia.service.WmChannelService;
import com.zhaozhaonews.wemedia.service.WmNewsAutoScanService;
import com.zhaozhaonews.wemedia.service.WmNewsService;
import com.zhaozhaonews.wemedia.service.WmUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author WanJl
 * @version 1.0
 * @title WmNewsAutoScanServiceImpl
 * @description
 * @create 2025/2/19
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class WmNewsAutoScanServiceImpl implements WmNewsAutoScanService {
    @Resource
    private WmNewsService wmNewsService;

    @Resource
    private GreenTextScan greenTextScan;

    @Resource
    private GreenImageScan greenImageScan;

    @Resource
    private FileStorageService fileStorageService;

    @Resource
    private WmChannelService wmChannelService;

    @Resource
    private WmUserService wmUserService;

    @Resource
    private IArticleClient articleClient;

    /**
     * 自媒体新闻自动审核
     *
     * @param newsId 新闻ID
     */
    @Override
    @Async  //标明当前的方法是一个异步方法
    public void autoScanWmNews(Integer newsId) {
        //1、查询自媒体新闻
        WmNews wmNews = wmNewsService.getById(newsId);
        if (wmNews == null) {
            throw new RuntimeException("WmNewsAutoScanServiceImpl--新闻不存在");
        }
        //2、判断当前新闻的状态，如果状态值为1说明是已发布，但未审核
        if (wmNews.getStatus().equals(WmNews.Status.SUBMIT.getCode())) {
            //2.1 从新闻内容中提取文本和图片
            Map<String, Object> textAndImages = handleTextAndImages(wmNews);

            //2.2 审核文本内容，调用阿里云接口
            //提取文本
            String textContent = (String) textAndImages.get("content");


            //调用阿里云接口审核文本内容
            Boolean isTextScan = handelTextScan(textContent, wmNews);
            if (isTextScan == false) return;

            //2.3 审核图片
            List<String> imagesList = (List<String>) textAndImages.get("images");
            if (imagesList != null && imagesList.size() > 0) {
                Boolean isImageScan = handelImageScan(imagesList, wmNews);
                if (isImageScan == false) return;
            }

            //4、审核成功 保存到运营端的新闻服务
            ResponseResult responseResult = saveAppArticle(wmNews);
            if (!responseResult.getCode().equals(200))
                throw new RuntimeException("WmNewsAutoScanServiceImpl--新闻审核，保存运营端新闻相关数据失败");

            //回填运营端新闻的article_id
            wmNews.setArticleId((long) responseResult.getData());
            //修改新闻内容
            updateWmNews(wmNews, (short) 9, WmNews.Status.PUBLISHED.getReason());
        }
    }

    /**
     * 审核后修改新闻内容
     *
     * @param wmNews
     * @param status
     * @param reason
     */
    private void updateWmNews(WmNews wmNews, short status, String reason) {
        wmNews.setStatus(status);
        wmNews.setReason(reason);
        wmNewsService.updateById(wmNews);
    }

    /**
     * 把新闻保存到运营端的新闻服务
     *
     * @param wmNews
     * @return
     */
    private ResponseResult saveAppArticle(WmNews wmNews) {
        ArticleDto dto = new ArticleDto();
        BeanUtils.copyProperties(wmNews, dto);
        //设置新闻布局
        dto.setLayout(wmNews.getType());
        //设置频道
        WmChannel wmChannel = wmChannelService.getById(wmNews.getChannelId());
        if (wmChannel != null) {
            dto.setChannelId(wmChannel.getId());
        }
        //设置作者
        dto.setAuthorId(wmNews.getUserId().longValue());
        WmUser wmUser = wmUserService.getById(wmNews.getUserId());
        if (wmUser != null)
            dto.setAuthorName(wmUser.getName());

        //设置新闻id
        if (wmNews.getArticleId() != null)
            dto.setId(wmNews.getArticleId());

        //设置修改时间
        dto.setCreatedTime(new Date());
        dto.setPublishTime(new Date());

        //进行远程调用，保存到运营端新闻表
        ResponseResult responseResult = articleClient.save(dto);

        return responseResult;
    }

    /**
     * 调用阿里云审核图片
     * 1、审核新闻内容图片
     * 2、审核新闻封面图片
     *
     * @param imageList
     * @param wmNews
     * @return
     */
    private Boolean handelImageScan(List<String> imageList, WmNews wmNews) {
        boolean isImageScan = true;
        if (imageList == null || imageList.size() == 0) return isImageScan;

        //去重图片
        imageList = imageList.stream().distinct().collect(Collectors.toList());
        //批量下载图片
        List<String> images = new ArrayList<>();
        for (String image : imageList) {
            //下载图片到临时位置
            String imagePath = fileStorageService.downLoadImage(image, "./");
            images.add(imagePath);
        }
        try {
            //审核图片
            for (String image : images) {
                Map map = greenImageScan.imageScan(image);
                if (!map.get("label").equals("nonLabel")) {
                    if ((Double) map.get("confidence") > 70) {//分值大于70，说明图片违禁
                        isImageScan = false;
                        updateWmNews(wmNews, (short) 2, WmNews.Status.FAIL.getReason());
                    } else {//否则图片合规
                        isImageScan = false;
                        updateWmNews(wmNews, (short) 3, WmNews.Status.ADMIN_AUTH.getReason());
                    }
                }
            }
        } catch (Exception e) {
            isImageScan = false;
            e.printStackTrace();
        }finally {
            images.stream().forEach(image -> {
                Boolean b = fileStorageService.deleteLoadFile(image);
            });
        }

        return isImageScan;
    }

    /**
     * 调用阿里云接口审核文本内容
     * 1、审核新闻内容
     * 2、审核新闻标题
     *
     * @param textContent
     * @param wmNews
     * @return
     */
    private Boolean handelTextScan(String textContent, WmNews wmNews) {
        boolean flag = true;
        //判断新闻内容以及标题是否为空
        if ((wmNews.getTitle() + textContent).length() == 0) return flag;

        //组合标题和内容
        String content = wmNews.getTitle() + "-" + textContent;

        //对字符串进行去空格
        content = content.replace(" ", "");

        //如果文本内容长度大于600，则将文本进行拆分，
        //content.length()>600
        // 599%600=0
        //601%600=1
        //1201%600=2
        if (content.length() < 600) {
            if (autoScanText(content, flag, wmNews) == false) return flag;
        }
        int current = 600;
        for (int i = 0; i < content.length() % current; i++) {
            String substring = StringUtils.substring(content, i, (content.length() % current) * i);
            if (autoScanText(substring, flag, wmNews) == false) return flag;
        }
        return flag;
    }

    public boolean autoScanText(String content, boolean flag, WmNews wmNews) {
        try {
            Map map = greenTextScan.greeTextScan(content);
            if (map != null) {
                if (map.get("lables") != null || map.get("lables") != "") {
                    List<Map> maps = JSON.parseArray("[" + map.get("reason") + "]", Map.class);
                    StringBuilder reason = new StringBuilder();
                    StringBuilder riskLevel = new StringBuilder();
                    maps.stream().forEach(m -> {
                        String riskTips = m.get("riskTips").toString();//审核的细分标签
                        String riskWords = m.get("riskWords").toString();//命中风险内容
                        riskLevel.append(m.get("riskLevel").toString());//违禁风险等级，high：高风险 medium：中风险 low：低风险
                        reason.append("细分标签------->" + riskTips);
                        reason.append("命中风险内容------->" + riskWords);
                    });
                    if (riskLevel.equals("high")) {
                        flag = false;
                        updateWmNews(wmNews, (short) 2, WmNews.Status.PUBLISHED.getReason() + reason);
                    }
                    if (riskLevel.equals("medium") || riskLevel.equals("low")) {
                        flag = false;
                        updateWmNews(wmNews, (short) 3, WmNews.Status.ADMIN_AUTH.getReason() + reason);
                    }
                }
            }
        } catch (Exception e) {
            flag = false;
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * 从新闻内容中提取文本和图片
     *
     * @param wmNews
     * @return
     */
    private Map<String, Object> handleTextAndImages(WmNews wmNews) {
        //创建可变字符串，存储文本内容
        StringBuilder textContent = new StringBuilder();
        //创建字符串集合，存储图片url
        List<String> imageList = new ArrayList<>();
        //1、从自媒体新闻的内容中提取文本和图片
        if (StringUtils.isNotBlank(wmNews.getContent())) {
            List<Map> maps = JSONArray.parseArray(wmNews.getContent(), Map.class);
            for (Map map : maps) {
                switch (map.get("type").toString()) {
                    case "text":
                        textContent.append(map.get("value").toString());
                        break;
                    case "image":
                        imageList.add(map.get("value").toString());
                        break;
                }
            }
        }
        //2、提取新闻的封面图片
        if (StringUtils.isNotBlank(wmNews.getImages())) {
            String[] split = wmNews.getImages().split(",");
            imageList.addAll(Arrays.asList(split));
        }
        //组合为Map集合
        Map<String, Object> textAndImages = new HashMap<>();
        textAndImages.put("content", textContent.toString());
        textAndImages.put("images", imageList);

        return textAndImages;
    }
}
